/// Popover 弹出框组件
/// 参照Element UI的Popover控件实现
library elegance_popover;

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/rendering.dart';
import '../../core/elegance_theme.dart';

/// 弹出框位置枚举
enum EPopoverPlacement {
  /// 顶部居中
  top,
  /// 顶部左侧
  topStart,
  /// 顶部右侧
  topEnd,
  /// 底部居中
  bottom,
  /// 底部左侧
  bottomStart,
  /// 底部右侧
  bottomEnd,
  /// 左侧居中
  left,
  /// 左侧顶部
  leftStart,
  /// 左侧底部
  leftEnd,
  /// 右侧居中
  right,
  /// 右侧顶部
  rightStart,
  /// 右侧底部
  rightEnd,
}

/// 弹出框触发方式枚举
enum EPopoverTrigger {
  /// 点击触发
  click,
  /// 悬浮触发
  hover,
  /// 焦点触发
  focus,
  /// 手动触发
  manual,
}

/// Popover 弹出框组件
class EPopover extends StatefulWidget {
  /// 创建弹出框组件
  const EPopover({
    super.key,
    required this.trigger,
    required this.content,
    this.title,
    this.placement = EPopoverPlacement.top,
    this.width,
    this.maxWidth = 300,
    this.showArrow = true,
    this.arrowSize = 10,
    this.offset = 0,
    this.disabled = false,
    this.triggerNode,
    this.openDelay = 0,
    this.closeDelay = 200,
    this.onShow,
    this.onHide,
  });

  /// 触发方式
  final EPopoverTrigger trigger;

  /// 弹出框内容
  final Widget content;

  /// 弹出框标题
  final Widget? title;

  /// 弹出框位置
  final EPopoverPlacement placement;

  /// 弹出框宽度
  final double? width;

  /// 弹出框最大宽度
  final double maxWidth;

  /// 是否显示箭头
  final bool showArrow;

  /// 箭头大小
  final double arrowSize;

  /// 偏移量
  final double offset;

  /// 是否禁用
  final bool disabled;

  /// 触发节点
  final Widget? triggerNode;

  /// 打开延迟时间（毫秒）
  final int openDelay;

  /// 关闭延迟时间（毫秒）
  final int closeDelay;

  /// 显示时的回调
  final VoidCallback? onShow;

  /// 隐藏时的回调
  final VoidCallback? onHide;

  @override
  State<EPopover> createState() => EPopoverState();
}

class EPopoverState extends State<EPopover> {
  /// 弹出框是否可见
  bool _visible = false;

  /// 触发元素的全局位置
  late Rect _triggerRect = Rect.zero;

  /// 弹窗层渲染对象
  final LayerLink _layerLink = LayerLink();

  /// 触发元素的GlobalKey
  final GlobalKey _triggerKey = GlobalKey();

  /// 弹出框内容的GlobalKey
  final GlobalKey _popoverKey = GlobalKey();

  /// 显示延迟定时器
  Timer? _showTimer;

  /// 隐藏延迟定时器
  Timer? _hideTimer;

  /// 鼠标位置跟踪器
  final StreamController<PointerEvent> _pointerEventController = StreamController<PointerEvent>();

  /// 指针位置记录
  Offset _pointerPosition = Offset.zero;

  /// 获取触发元素的位置
  void _getTriggerRect() {
    final renderBox = _triggerKey.currentContext?.findRenderObject() as RenderBox?;
    if (renderBox != null) {
      final newRect = renderBox.localToGlobal(Offset.zero) & renderBox.size;
      if (_triggerRect != newRect) {
        _triggerRect = newRect;
      }
    }
  }

  /// 检查鼠标是否在触发元素上
  bool _isPointerInTrigger() {
    return _triggerRect.contains(_pointerPosition);
  }

  /// 检查鼠标是否在弹出框上
  bool _isPointerInPopover() {
    final renderBox = _popoverKey.currentContext?.findRenderObject() as RenderBox?;
    if (renderBox == null) return false;
    
    final popoverRect = renderBox.localToGlobal(Offset.zero) & renderBox.size;
    return popoverRect.contains(_pointerPosition);
  }

  /// 处理指针移动事件
  void _handlePointerEvent(PointerEvent event) {
    if (!mounted || widget.disabled || widget.trigger != EPopoverTrigger.hover) {
      return;
    }

    _pointerPosition = event.position;
    final isInTrigger = _isPointerInTrigger();
    final isInPopover = _isPointerInPopover();
    
    // 仅在状态变化时进行处理
    if (_visible) {
      if (!isInTrigger && !isInPopover) {
        // 鼠标离开触发元素和弹出框
        _scheduleHidePopover();
      } else {
        // 鼠标仍在触发元素或弹出框上
        _showTimer?.cancel();
        _hideTimer?.cancel();
      }
    } else if (isInTrigger) {
      // 鼠标进入触发元素
      _scheduleShowPopover();
    }
  }

  /// 显示弹出框
  void _scheduleShowPopover() {
    if (widget.disabled || _visible) return;
    
    // 清除隐藏定时器
    _hideTimer?.cancel();
    
    // 如果已经有显示定时器，不需要重新设置
    if (_showTimer?.isActive ?? false) return;
    
    // 设置显示定时器
    _showTimer = Timer(Duration(milliseconds: widget.openDelay), () {
      if (mounted && !widget.disabled && !_visible && _isPointerInTrigger()) {
        _getTriggerRect();
        // 使用SchedulerBinding安全地更新状态
        SchedulerBinding.instance.addPostFrameCallback((_) {
          if (mounted && !widget.disabled && !_visible) {
            setState(() {
              _visible = true;
            });
            widget.onShow?.call();
          }
        });
      }
    });
  }

  /// 隐藏弹出框
  void _scheduleHidePopover() {
    if (widget.disabled || !_visible) return;
    
    // 清除显示定时器
    _showTimer?.cancel();
    
    // 如果已经有隐藏定时器，不需要重新设置
    if (_hideTimer?.isActive ?? false) return;
    
    // 设置隐藏定时器
    _hideTimer = Timer(Duration(milliseconds: widget.closeDelay), () {
      if (mounted && !widget.disabled && _visible && !_isPointerInTrigger() && !_isPointerInPopover()) {
        // 使用SchedulerBinding安全地更新状态
        SchedulerBinding.instance.addPostFrameCallback((_) {
          if (mounted && !widget.disabled && _visible) {
            setState(() {
              _visible = false;
            });
            widget.onHide?.call();
          }
        });
      }
    });
  }

  /// 切换弹出框显示状态
  void toggle() {
    if (widget.disabled) return;
    
    SchedulerBinding.instance.addPostFrameCallback((_) {
      if (mounted && !widget.disabled) {
        _getTriggerRect();
        setState(() {
          _visible = !_visible;
        });
        if (_visible) {
          widget.onShow?.call();
        } else {
          widget.onHide?.call();
        }
      }
    });
  }

  /// 立即显示弹出框
  void show() {
    if (widget.disabled || _visible) return;
    
    _showTimer?.cancel();
    _hideTimer?.cancel();
    
    SchedulerBinding.instance.addPostFrameCallback((_) {
      if (mounted && !widget.disabled && !_visible) {
        _getTriggerRect();
        setState(() {
          _visible = true;
        });
        widget.onShow?.call();
      }
    });
  }

  /// 立即隐藏弹出框
  void hide() {
    if (widget.disabled || !_visible) return;
    
    _showTimer?.cancel();
    _hideTimer?.cancel();
    
    SchedulerBinding.instance.addPostFrameCallback((_) {
      if (mounted && !widget.disabled && _visible) {
        setState(() {
          _visible = false;
        });
        widget.onHide?.call();
      }
    });
  }

  @override
  void initState() {
    super.initState();
    
    // 开始监听全局指针事件
    WidgetsBinding.instance.pointerRouter.addGlobalRoute((event) {
      if (event is PointerMoveEvent) {
        _pointerEventController.add(event);
      }
    });
    
    // 初始化触发元素位置
    SchedulerBinding.instance.addPostFrameCallback((_) {
      _getTriggerRect();
    });
  }

  @override
  void dispose() {
    _showTimer?.cancel();
    _hideTimer?.cancel();
    _pointerEventController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 构建触发节点
    Widget triggerNode = widget.triggerNode ?? 
      Container(
        child: Text('Click to open popover'),
      );

    // 根据触发方式添加相应的交互
    Widget interactiveTrigger;
    switch (widget.trigger) {
      case EPopoverTrigger.click:
        interactiveTrigger = InkWell(
          key: _triggerKey,
          onTap: toggle,
          child: triggerNode,
        );
        break;
      case EPopoverTrigger.hover:
        interactiveTrigger = Listener(
          key: _triggerKey,
          onPointerHover: _handlePointerEvent,
          onPointerMove: _handlePointerEvent,
          child: triggerNode,
        );
        break;
      case EPopoverTrigger.focus:
        interactiveTrigger = Focus(
          key: _triggerKey,
          onFocusChange: (hasFocus) {
            if (hasFocus) {
              show();
            } else {
              hide();
            }
          },
          child: triggerNode,
        );
        break;
      case EPopoverTrigger.manual:
        interactiveTrigger = Container(
          key: _triggerKey,
          child: triggerNode,
        );
        break;
    }

    return CompositedTransformTarget(
      link: _layerLink,
      child: Stack(
        children: [
          interactiveTrigger,
          if (_visible) ...[
            Positioned.fill(
              child: GestureDetector(
                onTap: widget.trigger == EPopoverTrigger.click ? hide : null,
                behavior: HitTestBehavior.translucent,
              ),
            ),
            CustomSingleChildLayout(
              delegate: _PopoverLayoutDelegate(
                layerLink: _layerLink,
                triggerRect: _triggerRect,
                placement: widget.placement,
                width: widget.width,
                maxWidth: widget.maxWidth,
                showArrow: widget.showArrow,
                arrowSize: widget.arrowSize,
                offset: widget.offset,
              ),
              child: _buildPopoverContent(),
            ),
          ],
        ],
      ),
    );
  }

  /// 构建弹出框内容
  Widget _buildPopoverContent() {
    final theme = EleganceTheme.of(context);
    
    List<Widget> contentWidgets = [];
    
    // 添加标题
    if (widget.title != null) {
      contentWidgets.add(
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 12, 16, 0),
          child: DefaultTextStyle(
            style: TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.bold,
              color: theme.textPrimaryColor,
            ),
            child: widget.title!, // 使用title属性
          ),
        ),
      );
    }
    
    // 添加内容
    contentWidgets.add(
      Padding(
        padding: EdgeInsets.fromLTRB(16, widget.title != null ? 8 : 12, 16, 12),
        child: DefaultTextStyle(
          style: TextStyle(
            fontSize: 14,
            color: theme.textRegularColor,
          ),
          child: widget.content, // 使用content属性
        ),
      ),
    );

    return Material(
      key: _popoverKey,
      elevation: 4,
      borderRadius: BorderRadius.circular(4),
      color: Colors.white,
      child: Container(
        width: widget.width,
        constraints: BoxConstraints(maxWidth: widget.maxWidth),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: contentWidgets,
        ),
      ),
    );
  }
}

/// 弹出框布局代理
class _PopoverLayoutDelegate extends SingleChildLayoutDelegate {
  final LayerLink layerLink;
  final Rect triggerRect;
  final EPopoverPlacement placement;
  final double? width;
  final double maxWidth;
  final bool showArrow;
  final double arrowSize;
  final double offset;

  _PopoverLayoutDelegate({
    required this.layerLink,
    required this.triggerRect,
    required this.placement,
    required this.width,
    required this.maxWidth,
    required this.showArrow,
    required this.arrowSize,
    required this.offset,
  });

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    return BoxConstraints(
      minWidth: width ?? 0,
      maxWidth: maxWidth,
      maxHeight: constraints.maxHeight,
    );
  }

  @override
  Offset getPositionForChild(Size size, Size childSize) {
    // 计算弹出框的位置
    final double x, y;
    
    // 根据不同的位置类型计算偏移量
    switch (placement) {
      case EPopoverPlacement.top:
        x = triggerRect.center.dx - childSize.width / 2;
        y = triggerRect.top - childSize.height - offset - (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.topStart:
        x = triggerRect.left;
        y = triggerRect.top - childSize.height - offset - (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.topEnd:
        x = triggerRect.right - childSize.width;
        y = triggerRect.top - childSize.height - offset - (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.bottom:
        x = triggerRect.center.dx - childSize.width / 2;
        y = triggerRect.bottom + offset + (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.bottomStart:
        x = triggerRect.left;
        y = triggerRect.bottom + offset + (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.bottomEnd:
        x = triggerRect.right - childSize.width;
        y = triggerRect.bottom + offset + (showArrow ? arrowSize : 0);
        break;
      case EPopoverPlacement.left:
        x = triggerRect.left - childSize.width - offset - (showArrow ? arrowSize : 0);
        y = triggerRect.center.dy - childSize.height / 2;
        break;
      case EPopoverPlacement.leftStart:
        x = triggerRect.left - childSize.width - offset - (showArrow ? arrowSize : 0);
        y = triggerRect.top;
        break;
      case EPopoverPlacement.leftEnd:
        x = triggerRect.left - childSize.width - offset - (showArrow ? arrowSize : 0);
        y = triggerRect.bottom - childSize.height;
        break;
      case EPopoverPlacement.right:
        x = triggerRect.right + offset + (showArrow ? arrowSize : 0);
        y = triggerRect.center.dy - childSize.height / 2;
        break;
      case EPopoverPlacement.rightStart:
        x = triggerRect.right + offset + (showArrow ? arrowSize : 0);
        y = triggerRect.top;
        break;
      case EPopoverPlacement.rightEnd:
        x = triggerRect.right + offset + (showArrow ? arrowSize : 0);
        y = triggerRect.bottom - childSize.height;
        break;

    }

    return Offset(x, y);
  }

  @override
  bool shouldRelayout(covariant _PopoverLayoutDelegate oldDelegate) {
    return oldDelegate.triggerRect != triggerRect ||
           oldDelegate.placement != placement ||
           oldDelegate.width != width ||
           oldDelegate.maxWidth != maxWidth ||
           oldDelegate.showArrow != showArrow ||
           oldDelegate.arrowSize != arrowSize ||
           oldDelegate.offset != offset;
  }
}